#ifndef __ASM_ARM_THREAD_INFO_H__
#define __ASM_ARM_THREAD_INFO_H__   

#include "linux/page.h"

#define THREAD_SIZE_ORDER	1
#define THREAD_SIZE		    (PAGE_SIZE << THREAD_SIZE_ORDER)
#define THREAD_START_SP		(THREAD_SIZE - 8)

#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE)

#ifndef __ASSEMBLY__

#include "linux/types.h"

struct task_struct;

typedef unsigned long mm_segment_t;
struct cpu_context_save
{
    unsigned long r4;
    unsigned long r5;
    unsigned long r6;
    unsigned long r7;
    unsigned long r8;
    unsigned long r9;
    unsigned long sl;
    unsigned long fp;
    unsigned long sp;
    unsigned long pc;
    unsigned long extra[2]; 
};

struct thread_info
{
    unsigned long flags;                 /* low level flags */
    int preempt_count;                   /* 0 => preemptable, <0 => bug */
    mm_segment_t addr_limit;             /* address limit */
    struct task_struct *task;            /* main task structure */
    unsigned int cpu;                             /* cpu */
    unsigned int cpu_domain;                      /* cpu domain */
    struct cpu_context_save cpu_context; /* cpu context */
    unsigned int syscall;                         /* syscall number */
};

register unsigned long current_stack_pointer asm ("sp");

static inline struct thread_info *current_thread_info(void)
{
    unsigned long stack_pointer = current_stack_pointer;
	
    stack_pointer &= ~(THREAD_SIZE - 1);

    return (struct thread_info *) (stack_pointer);
}

#define current_pt_regs(void) ({ (struct pt_regs *)	((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1;})


#endif
#endif